package com.wzh.oj.aop;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.wzh.oj.AuthCheck.AuthCheck;
import com.wzh.oj.common.ErrorCode;
import com.wzh.oj.exception.BusinessException;
import com.wzh.oj.model.entity.User;
import com.wzh.oj.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author wzh
 * @create 2023/4/3 19:40
 * @Description: 使用aop实现权限校验
 */
@Aspect
@Component
public class AuthInterceptor {

    @Resource
    private UserService userService;

    /**
     * 执行拦截
     *关于为什么用环绕：确保目标方法执行完之后仍有权限，如果用户在执行方法的期间失去了权限，从而可能导致一系列未经授权的操作导致数据泄露等问题
     * 返回对象为object类型，应为返回值为目标方法的返回值，而目标方法的返回值是不确定的,因此定义返回值的类型为object
     * @param joinPoint
     * @param authCheck
     * @return
     */
    @Around("@annotation(authCheck)")
    public Object doIntercept(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
        List<String> anyRole = Arrays.stream(authCheck.anyRole()).filter(StringUtils::isNoneBlank).collect(Collectors.toList());
        String musRole = authCheck.mustRole();
//         通过RequestContextHolder获取到当前请求的HttpServletRequest对象，从中获取到当前登录用户的信息。
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
//        获取当前登录的用户,
        User user = userService.getLoginUser(request);

        /**
         * 存在任意角色即可访问
         */
        if (CollectionUtils.isNotEmpty(anyRole)) {
            String userRole = user.getUserRole();
            if (!anyRole.contains(userRole)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        }
        /**
         *必须有所有权限才可以访问
         */
        if (StringUtils.isNotBlank(musRole)) {
            String userRole = user.getUserRole();
            if (!userRole.equals(userRole)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        }
//        放行
        return joinPoint.proceed();
    }


}
